Webhook Subscriptions

Get notified when things happen in a store

A webhook subscription tells Leal to POST a JSON payload to your URL whenever an event happens in the store, so you don’t have to poll. Subscribe to a list of events, or to ‘[“*”]` for every event (including ones added later). The full guide, with payload examples and signature verification code, is at www.tryleal.dev/developers/webhooks.

Events

  • customer.created: A customer joined the loyalty program.

  • customer.updated: A customer’s name, email, phone, birthday, metadata or marketing and SMS consent changed.

  • customer_card.created: A customer was issued a loyalty card. Includes the Apple Wallet and Google Wallet links.

  • stamp.earned: Stamps were added to a customer’s card, from a scan, the API or an adjustment.

  • stamp.removed: Stamps were taken off a customer’s card by an adjustment. Redeeming a reward sends reward.redeemed instead.

  • reward.unlocked: A customer now has enough stamps to redeem a reward. Sent once per reward, when the threshold is crossed.

  • reward.redeemed: A customer redeemed a reward.

Payload

Each delivery is an envelope: ‘{“id”: “evt_…”, “type”: “stamp.earned”, “timestamp”: “…”, “account_id”: 1, “data”: {…}}`. id is unique per event and stays the same across retries, so use it to ignore duplicates. customer.updated also carries previous_attributes with the old values of the fields that changed.

Subscriptions created from Zapier (and all subscriptions created before signing was introduced) use ‘payload_format: “flat”`, which sends the data object on its own. The event name is still available in the Leal-Event header. A flat subscription has exactly one event.

Older integrations send and read a single event string. That still works: event sets events to that one event, and responses include event whenever there is exactly one.

Verifying requests

Every delivery is signed using the Standard Webhooks scheme (www.standardwebhooks.com) with the subscription’s secret, via the webhook-id, webhook-timestamp and webhook-signature headers. Any Standard Webhooks library can verify it.

Retries

Respond with any 2xx status within 10 seconds. Anything else, or no response, is retried with increasing delays, up to 10 attempts over about four hours. Responding ‘410 Gone` deletes the subscription. A subscription that has not had a successful delivery for 3 days is disabled (`enabled: false`, `disabled_reason: “failing”`); re-enable it with PATCH once fixed.

index

GET /api/v1/accounts/:account_id/webhook_subscriptions

List webhook subscriptions

Returns every webhook subscription for the store, oldest first. Signing secrets are not included; fetch a single subscription to read its secret.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

event Must be a String Optional

Only return subscriptions that list this event (or ‘*`)

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store not found

Returns

Code: 200

An array of webhook subscriptions

Name Type Required Description
id Must be a Integer Required

Unique subscription ID

account_id Must be a Integer Required

Parent store ID

events Must be an array of String Required

Events delivered to this URL, or ‘[“*”]` for every event

event Must be a String Required

The event, when there is exactly one (kept for older integrations)

(nil allowed)
target_url Must be a String Required

URL that receives the POST requests

description Must be a String Required

Your own label for the subscription

(nil allowed)
payload_format Must be a String Required

envelope (default) or flat (the bare data object, used by Zapier)

enabled Must be one of: true, false, 1, 0. Required

Whether events are being delivered

disabled_at Must be a String Required

ISO 8601 time the subscription was disabled

(nil allowed)
disabled_reason Must be a String Required

disabled_by_user, failing or blocked_address

(nil allowed)
last_delivery_at Must be a String Required

ISO 8601 time of the most recent delivery attempt

(nil allowed)
last_delivery_status Must be a Integer Required

HTTP status your URL returned on the most recent attempt

(nil allowed)
last_delivery_error Must be a String Required

Why the most recent attempt failed

(nil allowed)
created_at Must be a String Required

ISO 8601 creation timestamp

updated_at Must be a String Required

ISO 8601 last-update timestamp

show

GET /api/v1/accounts/:account_id/webhook_subscriptions/:id

Show a webhook subscription

Returns a single subscription, including its signing secret and the result of the most recent delivery.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

id Must be a number. Required

Webhook subscription ID

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store or subscription not found

Returns

Code: 200

A webhook subscription, with its secret

Name Type Required Description
id Must be a Integer Required

Unique subscription ID

account_id Must be a Integer Required

Parent store ID

events Must be an array of String Required

Events delivered to this URL, or ‘[“*”]` for every event

event Must be a String Required

The event, when there is exactly one (kept for older integrations)

(nil allowed)
target_url Must be a String Required

URL that receives the POST requests

description Must be a String Required

Your own label for the subscription

(nil allowed)
payload_format Must be a String Required

envelope (default) or flat (the bare data object, used by Zapier)

enabled Must be one of: true, false, 1, 0. Required

Whether events are being delivered

disabled_at Must be a String Required

ISO 8601 time the subscription was disabled

(nil allowed)
disabled_reason Must be a String Required

disabled_by_user, failing or blocked_address

(nil allowed)
last_delivery_at Must be a String Required

ISO 8601 time of the most recent delivery attempt

(nil allowed)
last_delivery_status Must be a Integer Required

HTTP status your URL returned on the most recent attempt

(nil allowed)
last_delivery_error Must be a String Required

Why the most recent attempt failed

(nil allowed)
created_at Must be a String Required

ISO 8601 creation timestamp

updated_at Must be a String Required

ISO 8601 last-update timestamp

secret Must be a String Required

Signing secret (whsec_...). Use it to verify the webhook-signature header.

create

POST /api/v1/accounts/:account_id/webhook_subscriptions

Create a webhook subscription

Subscribes a URL to one or more events. The response includes the signing secret; store it to verify deliveries. The URL must be publicly reachable over https.

Events: customer.created, customer.updated, customer_card.created, stamp.earned, stamp.removed, reward.unlocked, reward.redeemed, or ‘*` for all of them.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

events Must be an array of String Optional

Events to subscribe to, or ‘[“*”]` for every event. Required unless event is given

event Must be a String Optional

A single event to subscribe to. Same as events with one entry

target_url Must be a String Required

Public https URL that will receive the POST requests

description Must be a String Optional

Your own label, up to 255 characters

payload_format Must be a String Optional

envelope (default) or flat. flat sends the bare data object and cannot be combined with ‘*`

enabled Must be one of: true, false, 1, 0. Optional

Create the subscription disabled by passing false (defaults to true)

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store not found
422 Validation failed – check `errors` for details

Returns

Code: 201

The new webhook subscription, with its secret

Name Type Required Description
id Must be a Integer Required

Unique subscription ID

account_id Must be a Integer Required

Parent store ID

events Must be an array of String Required

Events delivered to this URL, or ‘[“*”]` for every event

event Must be a String Required

The event, when there is exactly one (kept for older integrations)

(nil allowed)
target_url Must be a String Required

URL that receives the POST requests

description Must be a String Required

Your own label for the subscription

(nil allowed)
payload_format Must be a String Required

envelope (default) or flat (the bare data object, used by Zapier)

enabled Must be one of: true, false, 1, 0. Required

Whether events are being delivered

disabled_at Must be a String Required

ISO 8601 time the subscription was disabled

(nil allowed)
disabled_reason Must be a String Required

disabled_by_user, failing or blocked_address

(nil allowed)
last_delivery_at Must be a String Required

ISO 8601 time of the most recent delivery attempt

(nil allowed)
last_delivery_status Must be a Integer Required

HTTP status your URL returned on the most recent attempt

(nil allowed)
last_delivery_error Must be a String Required

Why the most recent attempt failed

(nil allowed)
created_at Must be a String Required

ISO 8601 creation timestamp

updated_at Must be a String Required

ISO 8601 last-update timestamp

secret Must be a String Required

Signing secret (whsec_...). Use it to verify the webhook-signature header.

update

PATCH /api/v1/accounts/:account_id/webhook_subscriptions/:id

Update a webhook subscription

Changes the URL, events, label or payload format, or turns the subscription off and on. Re-enabling a subscription that was disabled for failing clears its failure state.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

id Must be a number. Required

Webhook subscription ID

events Must be an array of String Optional

Replaces the list of events, or ‘[“*”]` for every event

event Must be a String Optional

A single event. Same as events with one entry

target_url Must be a String Optional

Public https URL that will receive the POST requests

description Must be a String Optional

Your own label, up to 255 characters

payload_format Must be a String Optional

envelope or flat

enabled Must be one of: true, false, 1, 0. Optional

false to pause deliveries, true to resume them

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store or subscription not found
422 Validation failed – check `errors` for details

Returns

Code: 200

The updated webhook subscription

Name Type Required Description
id Must be a Integer Required

Unique subscription ID

account_id Must be a Integer Required

Parent store ID

events Must be an array of String Required

Events delivered to this URL, or ‘[“*”]` for every event

event Must be a String Required

The event, when there is exactly one (kept for older integrations)

(nil allowed)
target_url Must be a String Required

URL that receives the POST requests

description Must be a String Required

Your own label for the subscription

(nil allowed)
payload_format Must be a String Required

envelope (default) or flat (the bare data object, used by Zapier)

enabled Must be one of: true, false, 1, 0. Required

Whether events are being delivered

disabled_at Must be a String Required

ISO 8601 time the subscription was disabled

(nil allowed)
disabled_reason Must be a String Required

disabled_by_user, failing or blocked_address

(nil allowed)
last_delivery_at Must be a String Required

ISO 8601 time of the most recent delivery attempt

(nil allowed)
last_delivery_status Must be a Integer Required

HTTP status your URL returned on the most recent attempt

(nil allowed)
last_delivery_error Must be a String Required

Why the most recent attempt failed

(nil allowed)
created_at Must be a String Required

ISO 8601 creation timestamp

updated_at Must be a String Required

ISO 8601 last-update timestamp

destroy

DELETE /api/v1/accounts/:account_id/webhook_subscriptions/:id

Delete a webhook subscription

Stops deliveries and deletes the subscription. This cannot be undone.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

id Must be a number. Required

Webhook subscription ID

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store or subscription not found

Returns

Code: 204

No content. The subscription was deleted.

send_test

POST /api/v1/accounts/:account_id/webhook_subscriptions/:id/test

Send a test event

Immediately sends a signed webhook.test event to the subscription’s URL and reports what happened, so you can check your endpoint and signature verification without waiting for real activity. Test events are not retried and do not count towards disabling the subscription.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

id Must be a number. Required

Webhook subscription ID

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store or subscription not found

Returns

Code: 200

The outcome of the test delivery

Name Type Required Description
delivered Must be one of: true, false, 1, 0. Required

True when your URL responded with a 2xx status

status Must be a Integer Required

HTTP status your URL returned

(nil allowed)
event_id Must be a String Required

The webhook-id of the test event

error Must be a String Required

Why the delivery failed

(nil allowed)

rotate_secret

POST /api/v1/accounts/:account_id/webhook_subscriptions/:id/rotate_secret

Rotate the signing secret

Replaces the subscription’s signing secret. Deliveries are signed with the new secret straight away, so update your receiver at the same time.

Parameters

Name Type Required Description
account_id Must be a number. Required

Store (account) ID

id Must be a number. Required

Webhook subscription ID

Error Codes

Code Description
401 Unauthorized – invalid or missing API token
404 Store or subscription not found

Returns

Code: 200

The webhook subscription, with its new secret

Name Type Required Description
id Must be a Integer Required

Unique subscription ID

account_id Must be a Integer Required

Parent store ID

events Must be an array of String Required

Events delivered to this URL, or ‘[“*”]` for every event

event Must be a String Required

The event, when there is exactly one (kept for older integrations)

(nil allowed)
target_url Must be a String Required

URL that receives the POST requests

description Must be a String Required

Your own label for the subscription

(nil allowed)
payload_format Must be a String Required

envelope (default) or flat (the bare data object, used by Zapier)

enabled Must be one of: true, false, 1, 0. Required

Whether events are being delivered

disabled_at Must be a String Required

ISO 8601 time the subscription was disabled

(nil allowed)
disabled_reason Must be a String Required

disabled_by_user, failing or blocked_address

(nil allowed)
last_delivery_at Must be a String Required

ISO 8601 time of the most recent delivery attempt

(nil allowed)
last_delivery_status Must be a Integer Required

HTTP status your URL returned on the most recent attempt

(nil allowed)
last_delivery_error Must be a String Required

Why the most recent attempt failed

(nil allowed)
created_at Must be a String Required

ISO 8601 creation timestamp

updated_at Must be a String Required

ISO 8601 last-update timestamp

secret Must be a String Required

Signing secret (whsec_...). Use it to verify the webhook-signature header.